package kotlincode

import java.security.acl.Owner
import kotlin.reflect.KProperty

fun main() {
//    delegate1()
//    delegate2()
//    delegate3()
    delegate4()
}

private fun delegate4(){
    var text: String by StringDelegate()
    println(text)
}

class StringDelegate(private var name: String = "hello") {
    operator fun getValue(thisRef: Owner?, property: KProperty<*>): String {
        return name
    }

    operator fun setValue(thisRef: Owner?, property: KProperty<*>, value: String) {
        name = value
    }
}

//            定义懒加载委托
//               ↓   ↓
val data: String by lazy {
    request()
}

fun request(): String {
    println("执行网络请求")
    return "网络数据"
}

fun delegate3() {
    println("开始")
    println(data)
    //process only one
    println(data)
}

private fun delegate2() {
    val item = Item()
    item.count = 10
    println(item.total)
    item.total = 99
    println(item.count)
}

/**
 * 注意，代码中的两处注释是关键：
 * 注释①，代表total属性的getter、setter会被委托出去；
 * 注释②，::count，代表total被委托给了count。这里的“::count”是属性的引用，它跟我们前面学过的函数引用是一样的概念。
 */
class Item {
    var count: Int = 0

    //              ①  ②
    //              ↓   ↓
    var total: Int by ::count
}

// 近似逻辑，实际上，底层会生成一个Item$total$2类型的delegate来实现

class Item2 {
    var count: Int = 0

    var total: Int
        get() = count
        set(value: Int) {
            count = value
        }
}


private fun delegate1() {
    UniversalDB(object : DB {
        override fun save() {
            println("Internal fun")
        }
    }).save()
    UniversalDB(SqlDB()).save()
    UniversalDB(GreenDB()).save()
}

interface DB {
    fun save()
}

class SqlDB : DB {
    override fun save() {
        println("save to sqlDB")
    }
}

class GreenDB : DB {
    override fun save() {
        println("save to greenDB")
    }
}

/**
 * equal [Chapter09.UniversalDB]
 */
class UniversalDB(db: DB) : DB by db
